import os
import sys
import time
import threading
import paramiko
from typing import List, Tuple, Dict, Any, Optional
from concurrent.futures import ThreadPoolExecutor

from mylogger import log_info_console, log_error_console, log_warning_console, log_info_file, log_warning_file
from serverconfig import ServerConfig

class TransferProgress:
    """
    传输进度显示类，用于跟踪文件传输进度并在控制台上显示进度条。
    
    Attributes:
        file_size: 文件总大小（字节）
        filename: 文件名
        debug_mode: 是否启用调试模式
        last_printed: 上次打印的字节数
        start_time: 传输开始时间
        last_valid_rate: 最后有效传输速率
        last_update_time: 最后更新时间
        total_transferred: 累计传输字节数
    """
    def __init__(self, file_size: int, filename: str, debug_mode: bool = False):
        """
        初始化传输进度对象。
        
        Args:
            file_size: 文件总大小（字节）
            filename: 文件名
            debug_mode: 是否启用调试模式
        """
        self.file_size = file_size
        self.filename = filename
        self.debug_mode = debug_mode
        self.last_printed = 0
        self.start_time = time.time()
        self.last_valid_rate = 0
        self.last_update_time = self.start_time
        self.total_transferred = 0  # 累计传输字节数
        
    def __call__(self, current: int, total: Optional[int] = None):
        """
        回调函数，用于更新和显示传输进度。
        
        Args:
            current: 当前已传输字节数
            total: 文件总字节数（可选）
        """
        if total is None:
            total = self.file_size

        # 确保当前传输量不超过总量
        if current >= total:
            current = total        
        percent = (current / total) * 100 if total > 0 else 0
        now = time.time()
        elapsed = now - self.start_time
        
        # 累计传输字节数
        self.total_transferred = current
        
        # 计算当前传输速率
        transferred = current - self.last_printed
        time_interval = now - self.last_update_time
        
        if time_interval > 0:
            current_rate = transferred / time_interval
            self.last_valid_rate = current_rate
        else:
            current_rate = self.last_valid_rate
        
        # 对于已完成的传输，使用整个传输过程的平均速率
        if current >= total and elapsed > 0:
            final_rate = self.total_transferred / elapsed
            current_rate = final_rate
            self.last_valid_rate = final_rate
        
        # 格式化传输速率
        if current_rate < 1024:
            rate_str = f"{current_rate:.1f} B/s"
        elif current_rate < 1024 * 1024:
            rate_str = f"{current_rate / 1024:.1f} KB/s"
        else:
            rate_str = f"{current_rate / (1024 * 1024):.1f} MB/s"
        
        # 更新最后打印的位置和时间
        self.last_printed = current
        self.last_update_time = now
        
        if self.debug_mode:
            bar_length = 30
            filled_length = int(bar_length * current / total)
            # 当完成传输时，确保进度条完全显示为█
            if current >= total:
                filled_length = bar_length
                percent = 100.0
            bar = '█' * filled_length + '-' * (bar_length - filled_length)
            
            current_str = self._format_size(current)
            total_str = self._format_size(total)
            
            # 显示已用时
            elapsed_str = self._format_time(elapsed)
            
            # 进度条显示
            sys.stdout.write(f"\r传输中 {self.filename} [{bar}] {percent:.1f}% ({current_str}/{total_str}) {rate_str} 用时: {elapsed_str}")
            sys.stdout.flush()
    
    @staticmethod
    def _format_size(size_bytes: int) -> str:
        """
        将字节大小格式化为可读的形式（B/KB/MB/GB）。
        
        Args:
            size_bytes: 字节大小
            
        Returns:
            str: 格式化后的大小字符串
        """
        if size_bytes < 1024:
            return f"{size_bytes} B"
        elif size_bytes < 1024 * 1024:
            return f"{size_bytes / 1024:.1f} KB"
        elif size_bytes < 1024 * 1024 * 1024:
            return f"{size_bytes / (1024 * 1024):.1f} MB"
        else:
            return f"{size_bytes / (1024 * 1024 * 1024):.1f} GB"
    
    @staticmethod
    def _format_time(seconds: float) -> str:
        """
        将秒数格式化为可读的时间格式（HH:MM:SS）。
        
        Args:
            seconds: 秒数
            
        Returns:
            str: 格式化后的时间字符串
        """
        hours, remainder = divmod(int(seconds), 3600)
        minutes, seconds = divmod(remainder, 60)
        return f"{hours:02d}:{minutes:02d}:{seconds:02d}"

def copy_file(scp_client, local_path: str, remote_path: str, debug_mode: bool = False) -> bool:
    """
    复制单个文件到远程服务器。
    
    Args:
        scp_client: SCP客户端
        local_path: 本地文件路径
        remote_path: 远程文件路径
        debug_mode: 是否启用调试模式
        
    Returns:
        bool: 复制是否成功
    """
    try:
        file_size = os.path.getsize(local_path)
        progress = TransferProgress(file_size, os.path.basename(local_path), debug_mode)
        scp_client.put(local_path, remote_path, callback=progress)
        progress(file_size, file_size)
        if debug_mode:
            sys.stdout.write("\n")
            sys.stdout.flush()
        return True
    except Exception as e:
        error_msg = f"复制文件 {local_path} 到 {remote_path} 时发生错误: {str(e)}"
        log_error_console(error_msg)
        if debug_mode:
            import traceback
            log_info_console(f"详细错误信息: {traceback.format_exc()}")
        return False

def create_remote_directory(scp_client, remote_dir: str, debug_mode: bool = False) -> bool:
    """
    在远程服务器上创建目录结构。
    
    Args:
        scp_client: SCP客户端
        remote_dir: 远程目录路径
        debug_mode: 是否启用调试模式
        
    Returns:
        bool: 创建是否成功
    """
    try:
        parts = remote_dir.split('/')
        current_path = ''
        
        if parts and parts[0] == '':
            current_path = '/'
            parts = parts[1:]
        
        for part in parts:
            if not part:
                continue
                
            if current_path.endswith('/'):
                current_path += part
            else:
                current_path += '/' + part
            
            try:
                scp_client.stat(current_path)
            except FileNotFoundError:
                if debug_mode:
                    log_info_console(f"创建远程目录: {current_path}")
                scp_client.mkdir(current_path)
            except Exception as e:
                if debug_mode:
                    log_info_console(f"检查/创建目录 {current_path} 时发生错误: {str(e)}")
        
        return True
    except Exception as e:
        error_msg = f"创建远程目录 {remote_dir} 时发生错误: {str(e)}"
        log_error_console(error_msg)
        if debug_mode:
            import traceback
            log_info_console(f"详细错误信息: {traceback.format_exc()}")
        return False

def _copy_file_with_client(scp_client, local_path: str, remote_path: str, shared_state: Dict[str, Any], debug_mode: bool = False) -> bool:
    """
    使用给定的SFTP客户端复制单个文件
    
    Args:
        scp_client: SFTP客户端
        local_path: 本地文件路径
        remote_path: 远程文件路径
        shared_state: 共享状态字典
        debug_mode: 是否启用调试模式
    
    Returns:
        bool: 是否复制成功
    """
    success = False
    
    try:
        # 获取文件大小
        file_size = os.path.getsize(local_path)
        filename = os.path.basename(local_path)
        
        # 记录文件开始传输
        log_info_file(f"开始传输文件 {filename}，大小: {TransferProgress._format_size(file_size)}")
        if debug_mode:
            log_info_console(f"开始传输文件 {filename}，大小: {TransferProgress._format_size(file_size)}")
        
        # 实时进度回调类，负责更新共享状态
        class RealTimeProgress:
            def __init__(self, file_size, filename, debug_mode, shared_state):
                self.transfer_progress = TransferProgress(file_size, filename, debug_mode)
                self.shared_state = shared_state
                self.last_updated_bytes = 0
                self.filename = filename
                self.file_size = file_size
                self.start_time = time.time()
                self.last_update_time = self.start_time
            
            def __call__(self, current, total=None):
                # 调用原始的TransferProgress回调
                self.transfer_progress(current, total)
                
                # 计算本次传输的字节数
                transferred_bytes = current - self.last_updated_bytes
                
                # 更新共享状态
                if transferred_bytes > 0:
                    with self.shared_state['lock']:
                        self.shared_state['total_size'] += transferred_bytes
                    self.last_updated_bytes = current
        
        # 使用实时进度回调
        progress = RealTimeProgress(file_size, filename, debug_mode, shared_state)
        
        # 传输文件
        scp_client.put(local_path, remote_path, callback=progress)
        
        # 确保最后一次完整更新
        progress(file_size, file_size)
        success = True
        
        # 记录传输成功
        log_info_file(f"文件传输成功: {local_path} -> {remote_path}")
        if debug_mode:
            log_info_console(f"文件传输成功: {local_path} -> {remote_path}")
            
    except Exception as e:
        error_msg = f"复制文件 {local_path} 到 {remote_path} 时发生错误: {str(e)}"
        log_error_console(error_msg)
        if debug_mode:
            import traceback
            log_info_console(f"详细错误信息: {traceback.format_exc()}")
        success = False
    
    finally:
        # 更新任务计数
        with shared_state['lock']:
            shared_state['completed'] += 1
            if success:
                shared_state['success'] += 1
                log_info_file(f"文件传输完成: {local_path} -> {remote_path}")
            else:
                shared_state['failed'] += 1
                log_info_file(f"文件传输失败: {local_path} -> {remote_path}")
    
    return success

def _copy_directory_with_client(scp_client, local_path: str, remote_path: str, shared_state: Dict[str, Any], debug_mode: bool = False) -> bool:
    """
    使用给定的SFTP客户端复制整个目录
    
    Args:
        scp_client: SFTP客户端
        local_path: 本地目录路径
        remote_path: 远程目录路径
        shared_state: 共享状态字典
        debug_mode: 是否启用调试模式
    
    Returns:
        bool: 是否复制成功
    """
    try:
        if not create_remote_directory(scp_client, remote_path, debug_mode):
            return False
        
        for root, dirs, files in os.walk(local_path):
            relative_path = os.path.relpath(root, local_path)
            if relative_path == '.':
                relative_path = ''
            
            remote_subdir = os.path.join(remote_path, relative_path).replace('\\', '/')
            
            if not create_remote_directory(scp_client, remote_subdir, debug_mode):
                return False
            
            for file in files:
                local_file_path = os.path.join(root, file)
                remote_file_path = os.path.join(remote_subdir, file).replace('\\', '/')
                
                if not _copy_file_with_client(scp_client, local_file_path, remote_file_path, shared_state, debug_mode):
                    log_warning_console(f"目录复制部分失败: {local_file_path}")
        
        # 目录传输完成后，更新处理的目录计数
        with shared_state['lock']:
            shared_state['processed_directories'] = shared_state.get('processed_directories', 0) + 1
        
        return True
    except Exception as e:
        error_msg = f"复制目录 {local_path} 到 {remote_path} 时发生错误: {str(e)}"
        log_error_console(error_msg)
        if debug_mode:
            import traceback
            log_info_console(f"详细错误信息: {traceback.format_exc()}")
        return False

def _is_local_server(server_config: ServerConfig) -> bool:
    """
    判断服务器配置是否为本地服务器
    
    Args:
        server_config: 服务器配置对象
        
    Returns:
        bool: 是否为本地服务器
    """
    localhosts = ['localhost', '127.0.0.1', '::1']
    return server_config.ip in localhosts

def _server_copy_task(args: Tuple[ServerConfig, List[Tuple[str, str]], bool, Dict[str, Any]]) -> Tuple[ServerConfig, bool]:
    """
    为单个服务器执行文件复制任务
    
    Args:
        args: 包含服务器配置、路径对、调试模式和共享状态的元组
    
    Returns:
        Tuple[ServerConfig, bool]: 服务器配置和是否成功的标志
    """
    server_config, path_pairs, debug_mode, shared_state = args
    server_success = True
    client = None
    scp_client = None
    
    # 记录这个服务器需要处理的任务数量
    task_count_for_server = len(path_pairs)
    
    # 跟踪已处理的任务数
    processed_tasks = 0
    
    try:
        # 记录服务器开始处理
        log_info_file(f"开始处理服务器 {server_config.name} 的 {task_count_for_server} 个任务")
        
        client = paramiko.SSHClient()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        
        if debug_mode:
            log_info_console(f"正在连接到 {server_config.name} ({server_config.ip}:{server_config.port})")
        
        client.connect(
            hostname=server_config.ip,
            port=server_config.port,
            username=server_config.user,
            password=server_config.password if server_config.password else None,
            timeout=server_config.timeout
        )
        
        log_info_file(f"已连接到 {server_config.name} ({server_config.ip}:{server_config.port})")
        if debug_mode:
            log_info_console(f"已成功连接到 {server_config.name}")
        
        # 获取Transport对象并创建SFTP客户端
        transport = client.get_transport()
        """
        通过 from_transport 方法设置窗口大小和数据包大小
        3MB窗口大小
        1MB数据包大小
        """
        window_size = 3 * 1024 * 1024   
        max_packet_size = 1048576       
        scp_client = paramiko.SFTPClient.from_transport(transport, window_size=window_size, max_packet_size=max_packet_size)
        if debug_mode:
            log_info_console(f"已创建SFTP客户端")
        
        # 逐个处理文件
        for local_path, remote_path in path_pairs:
            if debug_mode:
                log_info_console(f"准备处理: {local_path} -> {remote_path}")
            
            try:
                if os.path.isfile(local_path):
                    log_info_file(f"正在传输文件 {local_path} 到 {server_config.name}:{remote_path}")
                    if debug_mode:
                        log_info_console(f"正在传输文件 {local_path} 到 {server_config.name}:{remote_path}")
                    
                    remote_dir = os.path.dirname(remote_path)
                    if remote_dir and remote_dir != '/':
                        if not create_remote_directory(scp_client, remote_dir, debug_mode=debug_mode):
                            server_success = False
                            with shared_state['lock']:
                                shared_state['completed'] += 1
                                shared_state['failed'] += 1
                            processed_tasks += 1
                            continue
                    
                    if not _copy_file_with_client(scp_client, local_path, remote_path, shared_state, debug_mode):
                        server_success = False
                else:
                    log_info_file(f"正在传输目录 {local_path} 到 {server_config.name}:{remote_path}")
                    if debug_mode:
                        log_info_console(f"正在传输目录 {local_path} 到 {server_config.name}:{remote_path}")
                    
                    if not _copy_directory_with_client(scp_client, local_path, remote_path, shared_state, debug_mode):
                        server_success = False
                
                processed_tasks += 1
            except Exception as e:
                # 确保输出换行
                sys.stdout.write("\n")
                sys.stdout.flush()
                
                error_msg = f"处理 {local_path} 时发生错误: {str(e)}"
                log_error_console(error_msg)
                if debug_mode:
                    import traceback
                    log_info_console(f"详细错误信息: {traceback.format_exc()}")
                
                # 确保任务被标记为完成
                with shared_state['lock']:
                    shared_state['completed'] += 1
                    shared_state['failed'] += 1
                processed_tasks += 1
                server_success = False
    
    except Exception as e:
        # 处理连接或其他严重错误
        sys.stdout.write("\n")
        sys.stdout.flush()
        
        error_msg = f"连接到 {server_config.name} 时发生错误: {str(e)}"
        log_error_console(error_msg)
        if debug_mode:
            import traceback
            log_info_console(f"详细错误信息: {traceback.format_exc()}")
        server_success = False
        
        # 当服务器连接失败时，所有该服务器的任务都应被标记为失败
        with shared_state['lock']:
            remaining_tasks = task_count_for_server - processed_tasks
            if remaining_tasks > 0:
                shared_state['completed'] += remaining_tasks
                shared_state['failed'] += remaining_tasks
    
    finally:
        # 确保资源被正确关闭
        try:
            if scp_client:
                scp_client.close()
                if debug_mode:
                    log_info_console(f"已关闭SFTP连接")
            if client:
                client.close()
                log_info_file(f"已关闭与 {server_config.name} 的连接")
                if debug_mode:
                    log_info_console(f"已关闭与 {server_config.name} 的SSH连接")
        except Exception as e:
            # 关闭资源时发生异常也要记录
            log_warning_file(f"关闭与 {server_config.name} 的连接时发生错误: {str(e)}")
    
    return (server_config, server_success)

def batch_copy_multiple_paths(servers: List[ServerConfig], local_paths: List[str], 
                             remote_path: str, threads: int = 5, debug_mode: bool = False) -> Tuple[int, int, int]:
    """
    批量复制文件到多个服务器
    
    Args:
        servers: 服务器配置列表
        local_paths: 本地文件/目录路径列表
        remote_path: 远程目标路径
        threads: 线程数
        debug_mode: 是否启用调试模式
    
    Returns:
        Tuple[int, int, int]: 成功任务数、失败任务数、总传输字节数
    """
    if not servers:
        log_error_console("没有可用的服务器配置")
        return 0, 0, 0
    
    server_tasks = {}
    total_tasks = 0
    
    # 预先计算所有文件的总大小和总文件数
    total_files_size = 0
    total_files_count = 0
    directory_count = 0
    
    for server_config in servers:
        path_pairs = []
        for local_path in local_paths:
            if os.path.isfile(local_path):
                # 如果是文件，获取其大小
                try:
                    file_size = os.path.getsize(local_path)
                    total_files_size += file_size
                    total_files_count += 1
                except Exception as e:
                    log_info_file(f"无法获取文件 {local_path} 的大小: {str(e)}")
                
                file_name = os.path.basename(local_path)
                target_path = os.path.join(remote_path, file_name)
            else:
                # 如果是目录，递归计算所有文件的大小和数量
                directory_count += 1
                has_files = False
                try:
                    for root, _, files in os.walk(local_path):
                        for file in files:
                            file_path = os.path.join(root, file)
                            try:
                                total_files_size += os.path.getsize(file_path)
                                total_files_count += 1
                                has_files = True
                            except Exception as e:
                                log_info_file(f"无法获取文件 {file_path} 的大小: {str(e)}")
                except Exception as e:
                    log_info_file(f"无法获取目录 {local_path} 的文件大小: {str(e)}")
                
                dir_name = os.path.basename(local_path)
                target_path = os.path.join(remote_path, dir_name)
            
            path_pairs.append((local_path, target_path))
            total_tasks += 1
        
        server_tasks[server_config] = path_pairs
    
    # 初始化共享状态
    shared_state = {
        'lock': threading.Lock(),
        'completed': 0,
        'success': 0,
        'failed': 0,
        'total_size': 0,
        'start_time': time.time(),
        # 添加停止事件标志
        'stop_event': threading.Event() 
    }
    
    # 添加文件和目录相关的统计信息
    shared_state.update({
        'total_files_size': total_files_size,               # 所有文件的总大小
        'total_files_count': total_files_count,             # 保存总文件数
        'directory_count': directory_count,                 # 保存目录数
        'concurrency': min(threads, len(server_tasks)),     # 保存并发数量
        'processed_directories': 0,                         # 已处理的目录数
        'has_files_in_directories': total_files_count > 0   # 是否有文件在目录中
    })
    
    server_task_list = [(server_config, path_pairs, debug_mode, shared_state) 
                      for server_config, path_pairs in server_tasks.items()]
    
    start_time = shared_state['start_time']
    
    log_info_console(f"开始传输，共 {total_tasks} 个任务，使用 {min(threads, len(server_tasks))} 个线程")
    
    # 显示初始进度条
    sys.stdout.write(f"\r总体进度: 0/{total_tasks} (0.0%) - 成功: 0, 失败: 0, 进行中: {total_tasks} - "
                    f"已用时: 00:00:00, 预计剩余: --:--:-- - 平均速率: 0 B/s")
    sys.stdout.flush()
    
    def update_progress():
        """
        更新并显示总体传输进度的函数
        """
        # 跨平台检测
        is_windows = sys.platform.startswith('win')
        
        try:
            while True:
                # 检查是否应该停止
                if shared_state['stop_event'].is_set():
                    break
                    
                # 获取共享状态
                with shared_state['lock']:
                    completed_tasks = shared_state['completed']
                    success_count = shared_state['success']
                    fail_count = shared_state['failed']
                    total_size = shared_state['total_size']
                    start_time = shared_state['start_time']
                    processed_directories = shared_state.get('processed_directories', 0)
                    has_files_in_directories = shared_state.get('has_files_in_directories', False)
                    total_files_size = shared_state.get('total_files_size', 0)
                    total_files_count = shared_state.get('total_files_count', 0)
                    directory_count = shared_state.get('directory_count', 0)
                    concurrency = shared_state.get('concurrency', 1)
                    
                    # 检查是否所有任务都已完成
                    all_tasks_completed = completed_tasks >= total_tasks
                
                # 计算正在进行的任务数
                in_progress = max(0, total_tasks - completed_tasks)
                
                # 计算进度百分比 - 根据用户要求实现不同的进度计算方式
                if has_files_in_directories and total_files_size > 0:
                    # 如果目录中包含文件，按文件大小计算进度
                    percent = (total_size / total_files_size) * 100 if total_files_size > 0 else 0
                    # 限制进度百分比不超过100%，避免0/6000显示100%的错误
                    percent = min(percent, 100.0)
                else:
                    # 如果没有文件，按照目录数量计算进度
                    percent = (processed_directories / directory_count) * 100 if directory_count > 0 else 0
                
                # 确保百分比在有效范围内
                percent = max(0.0, min(percent, 100.0))
                
                # 实时计算时间信息
                now = time.time()
                elapsed = now - start_time
                elapsed_str = TransferProgress._format_time(elapsed)
                
                # 计算平均速率
                rate_str = "0 B/s"
                if elapsed > 0:
                    avg_rate = total_size / elapsed
                    if avg_rate < 1024:
                        rate_str = f"{avg_rate:.1f} B/s"
                    elif avg_rate < 1024 * 1024:
                        rate_str = f"{avg_rate / 1024:.1f} KB/s"
                    else:
                        rate_str = f"{avg_rate / (1024 * 1024):.1f} MB/s"
                
                # 计算剩余时间
                remaining_str = "--:--:--"
                
                if has_files_in_directories and total_files_size > 0 and elapsed > 0:
                    # 基于文件大小计算剩余时间
                    if total_size > 0:
                        # 平均传输速率: 已传输大小/已用时间
                        avg_transfer_rate = total_size / elapsed
                        # 剩余大小
                        remaining_size = total_files_size - total_size
                        # 剩余时间 = 剩余大小 / 平均传输速率
                        remaining_time = remaining_size / avg_transfer_rate if avg_transfer_rate > 0 else 0
                        
                        # 确保剩余时间合理,最多显示10小时
                        if remaining_time >= 0 and remaining_time < 36000: 
                            remaining_str = TransferProgress._format_time(remaining_time)
                
                # 构建进度字符串
                progress_str = f"总体进度: {completed_tasks}/{total_tasks} ({percent:.1f}%) - "
                progress_str += f"成功: {success_count}, 失败: {fail_count}, 进行中: {in_progress} - "
                progress_str += f"已用时: {elapsed_str}, 预计剩余: {remaining_str} - 平均速率: {rate_str}"
                
                # 强制清除并更新整行
                if is_windows:
                    # Windows上的清除方法
                    sys.stdout.write("\r" + " " * (len(progress_str) + 30))
                    sys.stdout.flush()
                    sys.stdout.write("\r" + progress_str)
                else:
                    # Linux/Unix上直接使用\r覆盖
                    sys.stdout.write("\r" + progress_str)
                
                # 强制刷新输出缓冲区
                sys.stdout.flush()
                
                # 确保所有任务都已完成，设置停止事件并退出循环
                if all_tasks_completed:
                    shared_state['stop_event'].set()
                    break
                
                # 调整刷新率
                time.sleep(0.1)  # 10Hz刷新率
                
        except Exception as e:
            # 捕获任何可能的异常
            log_info_file(f"进度更新线程发生错误: {str(e)}")
            sys.stdout.write("\n")
            sys.stdout.flush()
    
    # 创建进度显示线程
    progress_thread = threading.Thread(target=update_progress)
    progress_thread.daemon = True
    progress_thread.start()
    
    with ThreadPoolExecutor(max_workers=min(threads, len(server_tasks))) as executor:
        try:
            # 提交所有任务
            futures = []
            for task in server_task_list:
                future = executor.submit(_server_copy_task, task)
                futures.append(future)
            
            # 获取完成的任务结果
            import concurrent.futures
            for future in concurrent.futures.as_completed(futures):
                try:
                    server_config, server_success = future.result()
                    server_status = "成功" if server_success else "部分失败"
                    log_info_file(f"服务器 {server_config.name} 传输{server_status}，已完成任务: {shared_state['completed']}/{total_tasks}")
                except Exception as e:
                    log_error_console(f"处理任务时发生异常: {str(e)}")
                    with shared_state['lock']:
                        pass
        except KeyboardInterrupt:
            log_warning_console("\n\n程序被用户中断，正在取消所有未完成的任务...")
            executor.shutdown(wait=False)
            # 设置停止事件标志
            shared_state['stop_event'].set()
            
            # 获取当前状态用于显示
            with shared_state['lock']:
                completed_tasks = shared_state['completed']
                success_count = shared_state['success']
                fail_count = shared_state['failed']
                total_size = shared_state['total_size']
            
            # 确保进度线程先结束
            if progress_thread.is_alive():
                progress_thread.join(timeout=1.0)
            
            elapsed = time.time() - start_time
            if elapsed > 0:
                avg_rate = total_size / elapsed
                if avg_rate < 1024:
                    rate_str = f"{avg_rate:.1f} B/s"
                elif avg_rate < 1024 * 1024:
                    rate_str = f"{avg_rate / 1024:.1f} KB/s"
                else:
                    rate_str = f"{avg_rate / (1024 * 1024):.1f} MB/s"
            else:
                rate_str = "0 B/s"
            
            elapsed_str = TransferProgress._format_time(elapsed)
            
            # 计算最终进度百分比
            percent = (completed_tasks / total_tasks * 100) if total_tasks > 0 else 0.0
            percent = max(0.0, min(percent, 100.0))
            
            sys.stdout.write(f"\r总体进度: {completed_tasks}/{total_tasks} ({percent:.1f}%) - "
                            f"成功: {success_count}, 失败: {fail_count} - "
                            f"已用时: {elapsed_str}, 预计剩余: --:--:-- - 平均速率: {rate_str}")
            sys.stdout.write("\n")
            sys.stdout.flush()
            
            log_info_console(f"传输已中断 - 已完成: {completed_tasks}/{total_tasks}, 成功: {success_count}, 失败: {fail_count}")
            raise
        except Exception as e:
            log_error_console(f"执行传输任务时发生未预期的错误: {str(e)}")
            sys.stdout.write("\n")
            sys.stdout.flush()
    
    # 设置停止事件标志，确保进度线程停止
    shared_state['stop_event'].set()
    
    # 确保最终状态显示正确
    with shared_state['lock']:
        completed_tasks = shared_state['completed']
        success_count = shared_state['success']
        fail_count = shared_state['failed']
        total_size = shared_state['total_size']
        processed_directories = shared_state.get('processed_directories', 0)
        directory_count = shared_state.get('directory_count', 0)
        has_files_in_directories = shared_state.get('has_files_in_directories', False)
    
    # 确保进度线程先结束
    if progress_thread.is_alive():
        progress_thread.join(timeout=1.0)
    
    elapsed = time.time() - start_time
    if elapsed > 0:
        avg_rate = total_size / elapsed
        if avg_rate < 1024:
            rate_str = f"{avg_rate:.1f} B/s"
        elif avg_rate < 1024 * 1024:
            rate_str = f"{avg_rate / 1024:.1f} KB/s"
        else:
            rate_str = f"{avg_rate / (1024 * 1024):.1f} MB/s"
    else:
        rate_str = "0 B/s"
    
    elapsed_str = TransferProgress._format_time(elapsed)
    
    # 计算最终进度百分比
    if total_tasks > 0:
        percent = (completed_tasks / total_tasks) * 100
    else:
        percent = 0.0
    
    # 确保百分比在有效范围内
    percent = max(0.0, min(percent, 100.0))
    
    sys.stdout.write(f"\r总体进度: {completed_tasks}/{total_tasks} ({percent:.1f}%) - "
                    f"成功: {success_count}, 失败: {fail_count} - "
                    f"已用时: {elapsed_str}, 预计剩余: --:--:-- - 平均速率: {rate_str}")
    sys.stdout.write("\n")
    sys.stdout.flush()
    
    total_time = TransferProgress._format_time(elapsed)
    sys.stdout.write("\n")  # 添加换行符
    sys.stdout.flush()
    log_info_console(f"传输完成! 总耗时: {total_time}")
    
    # 打印传输摘要，传入has_directories参数
    print_summary(success_count, fail_count, total_size, directory_count > 0)
    
    return success_count, fail_count, total_size

def print_summary(success_count: int, fail_count: int, total_size: int, has_directories: bool = False) -> None:
    """
    打印传输结果摘要
    
    Args:
        success_count: 成功的任务数
        fail_count: 失败的任务数
        total_size: 总传输字节数
        has_directories: 是否包含目录传输
    """
    total = success_count + fail_count
    
    # 当有目录传输时，即使任务计数为0也必须显示传输结果
    if total == 0 and not has_directories:
        log_info_console("没有执行任何传输任务")
        return
    
    # 格式化传输结果可读
    if total_size < 1024:
        size_str = f"{total_size} B"
    elif total_size < 1024 * 1024:
        size_str = f"{total_size / 1024:.2f} KB"
    elif total_size < 1024 * 1024 * 1024:
        size_str = f"{total_size / (1024 * 1024):.2f} MB"
    else:
        size_str = f"{total_size / (1024 * 1024 * 1024):.2f} GB"
    
    if fail_count == 0:
        if total > 0:
            log_info_console(f"所有文件传输成功! 共 {success_count} 个任务，总传输量: {size_str}")
        elif has_directories:
            log_info_console(f"目录传输成功! 总传输量: {size_str}")
    else:
        log_info_console(f"传输完成 - 成功: {success_count}, 失败: {fail_count}, 总传输量: {size_str}")